<?
// Инициализация теста
include mst_modpath($MT_mod_name,'atest/mysql.php');
function atest_mod_sharpobj($level)
{   // Возврощает списко тестовых функций
    switch ($level)
    {
        case 'unit':
            // Функции модульного тестирования
            // (изолированный функционал)
            return array(
                        'atest_mod_sharpobj_unit_datapath',
                        'atest_mod_sharpobj_unit_dataint',
                        'atest_mod_sharpobj_unit_datadata',
                        'atest_mod_sharpobj_unit_dataarray',
						'atest_mod_sharpobj_unit_stformat');
        break;
        case 'func':
            // Функции функционального тестирования
            // Приемочнгое тестирование
            return array('atest_mod_sharpobj_func_processor',
						'atest_mod_sharpobj_func_simplemysql',
						'atest_mod_sharpobj_func_mysql_create',
						'atest_mod_sharpobj_func_integrated',
            			'atest_mod_sharpobj_func_standartcalls',
            			'atest_mod_sharpobj_func_mysqlflex',
            			'atest_mod_sharpobj_func_overload');
        break;

    }
}


// echo microtime(true);
function atest_mod_sharpobj_unit_datapath()
{   // Тестируем работу с путями к данным
    $start = microtime(true);
    $ok = true;
    $obj = new sharpobj_data_item_data();
    $datapath[1]='aaa/bbb/ccc';
    $isnull[1] = false;
    $nextname[1] = 'aaa';
    $nextpath[1] = 'bbb/ccc';
    $isnext[1] = false;
    
    $datapath[2]='aaa';
    $isnull[2] = false;
    $nextname[2] = 'aaa';
    $nextpath[2] = null;
    $isnext[2] = true;
    
    $datapath[3]='';
    $isnull[3] = true;
    $nextname[3] = null;
    $nextpath[3] = null;
    $isnext[3] = false;
    
    $datapath[4]=null;
    $isnull[4] = true;
    $nextname[4] = null;
    $nextpath[4] = null;
    $isnext[4] = false;
    
    echo '<pre>';
    foreach ($datapath as $i=>$dp)
    {
        // Проверка на текущий путь
        if ($obj->pathThis($dp) != $isnull[$i])
        {
            // Ошибка
            echo "\nНеправильно определен нулевой путь {$i} {$dp}";
            $ok = false;
        }
        // Проверка на следующий элемент
        if ($obj->pathNextName($dp) != $nextname[$i])
        {
            // Ошибка
            echo "\nНеправильно определен следующий элемент {$i} {$dp}";
            $ok = false;
        }
        // Правильно ли опознан следующий элемент первого уровня в пути?
        if ($obj->pathNextLast($dp) != $isnext[$i])
        {
            // Ошибка
            echo "\nНеправильно определено окончание вложенности {$i} {$dp}";
            $ok = false;
        }
        // Правильно ли определен следующий элемент?
        if ($obj->pathNextPath($dp) != $nextpath[$i])
        {
            // Ошибка
            echo "\nНеправильно определен следующий путь {$i} {$dp}";
            $ok = false;
        }
        
    }
    echo round(microtime(true) - $start,6);
    echo '</pre>';
    return $ok;
}

function atest_mod_sharpobj_unit_dataint()
{   // Проверяем работу с данными int
    $start = microtime(true);
    $ok = true;
    // $obj->addItem('int',array('len_max'=>'10','len_min'=>'0'),'ee.tt');
    // $obj_int = new sharpobj_data_item_int(array('len_max'=>'10','len_min'=>'0'),'ttt.rrr');
    // $obj->addItem('string',array('len_max'=>'11','len_min'=>'0'),'ee.tt');
    echo '<pre>';   
    $obj = new sharpobj_data_item_int();
    
    // **************
    // Проверки филтра plain
    // **************
    
    // Правильные данные
    $value = 100;
    $obj->set('plain',$value);
    if ($value != $obj->get('plain'))
    {
        echo "\n".$value ."!=". $obj->get('plain');
        $ok = false;
    }
    
    // Неправильные данные
    $value = '100a';
    $obj->set('plain',$value);
    if ($obj->getNullValue() != $obj->get('plain'))
    {
        echo "\n".$obj->getNullValue() ."!=". $obj->get('plain');
        $ok = false;
    }
    $res = $obj->get('validate');
    if ($res['error_code'] != 'format')
    {
        echo "\nФильтр validate не возвращает код ошибки";
        print_r($res);
        $ok = false;
    }

    // Незначащие пробелы
    $value = '101';
    $obj->setOption('trim',true);
    $obj->set('plain',' '.$value.' ');
    if ($value != $obj->get('plain'))
    {
        echo "\nНе убираются незначащие пробелы";
        echo "\n".$value ."!=". $obj->get('plain');
        $ok = false;
    }
    $res = $obj->get('validate');
    if (!($res===false))
    {
        echo "\nФильтр validate возвращает ложную ошибку";
        print_r($res);
        $ok = false;
    }
    
    // Произвольное нулевое значение
    $null_value = 11;
    $obj->setNullValue($null_value);
    $value = null;
    $obj->set('plain',$value);
    if ($null_value != $obj->get('plain'))
    {
        echo "\n".$null_value ."!=". $obj->get('plain');
        $ok = false;
    }
    $obj->setNullValue(null);
    
    // Запрет нулевого значения
    $obj->setOption('null',false);
    $obj->set('plain',null);
    if (!$obj->isError())
    {
        echo "\nНе обрабатывается запрет на нулевые входные данные";
    }
    
    // Значение по умолчанию
    $value = 44;
    $obj->setDefaultValue($value);
    $obj->set('default');
    if ($obj->get('plain') != $value)
    {
        echo "\nНе обрабатывается значение по умолчанию";
        echo "\n".$value ."!=". $obj->get('plain');
        $ok = false;
    }
    
    // Сохранность нулевого значения
    $obj->clear();
    if (!is_null($obj->getP()) 
            OR !is_null($obj->get('sql')))
    {
        echo "\nНеправильно отображается нулевое значение";
        $ok = false;
    }
    
    // $obj2 = new sharpobj_data_item_data();
    // $obj2->set('plain',null);
    echo round(microtime(true) - $start,6);
    echo '</pre>';
    return $ok;
}

function atest_mod_sharpobj_unit_datadata()
{   // Проверяем работу с вложенными элементами
    $start = microtime(true);
    $ok = true;
    // $obj->addItem('int',array('len_max'=>'10','len_min'=>'0'),'ee.tt');
    // $obj_int = new sharpobj_data_item_int(array('len_max'=>'10','len_min'=>'0'),'ttt.rrr');
    // $obj->addItem('string',array('len_max'=>'11','len_min'=>'0'),'ee.tt');
    echo '<pre>';
    // Создаем объект
    $obj = new sharpobj_data_item_data();
    // Создаем вложенные элементы
    $obj->addItem('a','int');
    $obj->addItem('b','int');
    // Создаем вложенные элементы второго уровня
    $obj->addItem('r','data');
    $obj->addItem('r/a','int');
    $obj->addItem('r/b','int');
    // Проверяем вложенный элемент первого уровня
    $value = 3;
    $obj->set('plain',$value,'a');
    if ($obj->get('plain','a') != $value)
    {
        echo "\nНеправильно работают вложенные элементы первого уровня";
        echo "\n".$value ."!=". $obj->get('plain','a');
        $ok = false;
    }
    // Проверяем вложенный элемент второго уровня
    $value = 4;
    $value2 = 5;
    $obj->set('plain',$value2,'b');
    $obj->set('plain',$value,'r/b');
    if ($obj->get('plain','r/b') != $value)
    {
        echo "\nНеправильно работают вложенные элементы первого уровня";
        echo "\n".$value ."!=". $obj->get('plain','r/b');
        $ok = false;
    }
    if ($obj->get('plain','b') != $value2)
    {
        echo "\nНеправильно работают вложенные элементы первого уровня (затируют элементы первого уровня)";
        echo "\n".$value2 ."!=". $obj->get('plain','b');
        $ok = false;
    }
    $obj->set('plain',$value2,'b');
    if ($obj->get('plain','r/b') != $value)
    {
        echo "\nНеправильно работают вложенные элементы первого уровня (затираются элементами первого уровня)";
        echo "\n".$value ."!=". $obj->get('plain','r/b');
        $ok = false;
    }
    
    // Проверяем клонирование
    $c_obj = clone $obj;
    $c_a = $c_obj->cloneItem('a');
    $c_rb = $c_obj->cloneItem('r/b');
    $obj->set('plain',10,'a');
    $c_obj->set('plain',11,'a');
    $obj->set('plain',16,'r/a');
    $c_obj->set('plain',17,'r/a');
    $c_a->set('plain',12);
    $c_rb->set('plain',15);
    if ($c_obj->get('plain','a') == $c_a->get('plain'))
    {
        echo "\nСохранение зависимости при клонировании вложенного элемента";
        $ok = false;
    }
    if ($c_obj->get('plain','r/b') == $c_rb->get('plain'))
    {
        echo "\nСохранение зависимости при клонировании вложенного элемента второго уровня";
        $ok = false;
    }
    if ($c_obj->get('plain','a') == $obj->get('plain','a'))
    {
        echo "\nСохранение зависимости при клонировании объекта data\n";
        print_r($obj);
        print_r($c_obj);
        $ok = false;
    }
    if ($c_obj->get('plain','r/a') == $obj->get('plain','r/a'))
    {
        echo "\nСохранение зависимости при клонировании объекта data\n";
        print_r($obj);
        print_r($c_obj);
        $ok = false;
    }    
    
    // Рекурсивные фильтры
    $value = array('a'=>1,'b'=>2,'r'=>array('a'=>3,'b'=>4));
    $obj->set('plain',$value);
    $value2 = $obj->get('plain');
    if ($value != $value2)
    {
        echo "\nНеправильная работа с рекурсивными фильтрами\n";
        print_r($value);
        print_r($value2);
        print_r($obj);
        // var_dump($obj->isEmpty('r'));
        $ok = false;
    }
    
    // Рекурсивная проверка состояний
    $value = array('a'=>1,'b'=>2,'r'=>array('a'=>3,'b'=>4));
    $obj->set('plain',$value);
    if (!$obj->isData())
    {
        echo "\nНе определяется рекурсивное состояние data\n";
        print_r($obj);
        $ok = false;
    }
    $value = array('a'=>1,'b'=>2,'r'=>array('a'=>'a3','b'=>4));
    $obj->set('plain',$value);
    if (!$obj->isError())
    {
        echo "\nНе определяется рекурсивное состояние error\n";
        print_r($obj);
        $ok = false;
    }
    
    // Очистка атрибута
    $obj->clear('r/b');
    if (!$obj->isEmpty('r/b'))
    {
        echo "\nОчистка атрибутов не происходит\n";
        print_r($obj);
        $ok = false;
    }

    
    // print_r($obj);
    // print_r($c_obj);
    /*
    // Проверка клонирования
    $s_a = $obj->cloneItem('a');
    $s_rb = $obj->cloneItem('r/b');
    $s_a->set('plain',88);
    $s_rb->set('plain',99);
    print_r($s_a);
    print_r($s_rb);
    
    
    $obj2 = clone $obj;
    $obj2->delItem('b');
    $obj2->set('plain',33,'r/a');
    print_r($obj2);
    */
    echo round(microtime(true) - $start,6);
    echo '</pre>';
    return $ok;
}
function atest_mod_sharpobj_unit_dataarray()
{   // Проверяем работу с вложенными элементами
    $start = microtime(true);
    $ok = true;

    echo '<pre>';
    // Создаем объект
    $obj = new sharpobj_data_item_array();
    // Создаем вложенные элементы
    $obj->addItem('a','int');
    $obj->addItem('b','int');
    $obj->addItem('c','int');
    $obj->add(null,'int');
    $obj->add(null,'int');
    $obj->add(null,'int');
    $obj->add(null,'int');
    foreach ($obj as $k=>$v)
    {
        if (!($v instanceof sharpobj_data_item_int))
        {
            echo "\nНеправильная работа итератора\n";
            print_r($v);
            $ok = false;
        }
    }
    if ($obj->count()!=7)
    {
        echo "\nНеправильное количество элементов\n";
        print_r($obj);
        $ok = false;
    }
    unset($obj);
    // Создаем объект
    $obj = new sharpobj_data_item_array();
    $a = array('a'=>321,'b'=>3.14,'c'=>'aaa');
    $obj->set('plain',$a);
    if ($obj->get('plain','a')!== $a['a']  
            AND $obj->get('plain','b')!== $a['b']
            AND $obj->get('plain','c')!== $a['c'])
    {
        echo "\nЗначения или тип элементов объекта не совпадает с первоначальным массивом\n";
        print_r($obj);
        $ok = false;              
    }
    $b = $obj->get('plain');
    if ($b['a']!== $a['a']  
            AND $b['b']!== $a['b']
            AND $b['c']!== $a['c'])
    {
        echo "\nЗначения или тип элементов полученного из объекта массива не совпадает с первоначальным массивом\n";
        var_dump($b);
        $ok = false;              
    }
    
    
 
    echo round(microtime(true) - $start,6);
    echo '</pre>';
    return $ok;
}
function atest_mod_sharpobj_unit_stformat()
{   // Тестируем класс формата хранилища
	$start = microtime(true);
    $ok = true;
    echo '<pre>';
	// Создаем формат базы
	$format = new sharpobj_storage_format();
	$format->addItem('a','a_int','int');
	$format->addItem('b','b_str','string');
	// Создаем экземпляр контейнера
	$dataobj1 = $format->getObj();
	$dataobj1->set('plain',array('a'=>123,'b'=>'rrr"ttt'));
	// Проверяем вывод списка имен колонок
	if ($format->getColNames(null,'`', ', ')!='`a_int`, `b_str`')
	{
		echo "Неправильно создана строка с именами колонок БД\n";
		echo $format->getColNames(null,'`', ', ')."\n";
		$ok = false;
	}
	// Проверяем список значений
	if ($format->getColVals($dataobj1,'sql','"', ', ')!='"123", "rrr\"ttt"')
	{
		echo "Неправильно создана строка со значениями колонок БД\n";
		echo $format->getColVals($dataobj1,'sql','"', ', ')."\n";
		$ok = false;
	}
	// Создаем экземпляр контейнера
	$dataobj1 = $format->getObj();
	$dataobj1->set('plain','rrr"ttt','b');
	// Проверяем вывод списка имен колонок с пустыми значениями
	if ($format->getColNames($dataobj1,'`', ', ','',true)!='`b_str`')
	{
		echo "Неправильно создана строка с именами колонок БД\n";
		echo $format->getColNames($dataobj1,'`', ', ','',true)."\n";
		print_r($dataobj1);
		$ok = false;

	}
	// Проверяем список значений с пустыми значениями
	if ($format->getColVals($dataobj1,'sql','"', ', ',true)!='"rrr\"ttt"')
	{
		echo "Неправильно создана строка со значениями колонок БД\n";
		echo $format->getColVals($dataobj1,'sql','"', ', ',true)."\n";
		print_r($dataobj1);
		$ok = false;
	}	
	echo round(microtime(true) - $start,6);
    echo '</pre>';
    return $ok;
}


function atest_mod_sharpobj_func_processor()
{   // Тестируем работу связки обработки данных

    $ok = true;
	$start = microtime(true);
    echo '<pre>';
    // Процессор
    class atest_mod_sharpobj_func_processor_processor extends sharpobj_processor
    {
        function act_test($a)
        {
            $b = clone $a;
            $b->set('plain',$b->get('plain')+2);
            return $b;
        }
    }
    $proc = new atest_mod_sharpobj_func_processor_processor();
    
    // Серверный порт
    $port_s = new sharpobj_port_server('pr',$proc);
    
    // Клиентский порт
    $port_c = new sharpobj_port_client_int('ps',$port_s);
    
    $dataobj = new sharpobj_data_item_int();
    $dataobj->set('plain',10);
    
    $res = $port_c->query('test',$dataobj);
	// var_dump($res);
	// var_dump($dataobj);
    if ($res != ($dataobj->get('plain')+2))
    {
        echo "\nСбой в цепочке: результат не соответствует ожидаемому\n";
        print_r($res);
        $ok = false;
    }
	// Считаем, сколько заняло исполнение
	echo round(microtime(true) - $start,4);
    echo '</pre>';
    return $ok;
}

function atest_mod_sharpobj_func_integrated()
{   // Тестируем работу связки обработки данных

    $ok = true;
	$start = microtime(true);
    echo '<pre>';
    // Процессор
    class atest_mod_sharpobj_func_p1 extends sharpobj_processor
    {
		function __construct()
		{
			// Создаем справочники
			// Задаем формат справочника
			$format = new sharpobj_storage_format();
			$format->addItem('a','a_int','int');
			$format->addItem('b','b_str','string');
			// Объявляем справочник
			$DB_t1 = new sharpobj_storage_simplemysql($format,
			array('tbname'=>'atest_sharpobj_t1','idfield'=>'id'));
			// Подключаемся к базе
			// $mysql_conn = mysql_connect('localhost','root','');
			// mysql_select_db('my-site-srv',$mysql_conn);
			// $DB_t1->setConnection($mysql_conn);
			// Добавляем справочник к процессору
			$this->storageAdd('t1',$DB_t1);
		}
        function act_get_blankobjt1($dataobj=null)
        {
			// Возвращаем пустой объект данных хранилища t1
            return $this->storageLink('t1')->getObj();
        }
        function act_addt1($dataobj)
        {
			// Добавляем объект в хранилище
            return $this->storageLink('t1')->insert($dataobj);
        }
        function act_gett1($id)
        {
			// Получаем объект из хранилища
            return $this->storageLink('t1')->get($id);
        }
        function act_test($a)
        {
            $b = clone $a;
            $b->set('plain',$b->get('plain')+2);
            return $b;
        }
    }
	// Создаем экземпляр процессор
    $proc1 = new atest_mod_sharpobj_func_p1();
    // Серверный порт
    $port_s1 = new sharpobj_port_server('proc1',$proc1);
    // Клиентский порт
    $port_c = new sharpobj_port_client_int('port_s1',$port_s1);
    
	// *********************
	// Работаем с клиентом
	// Получаем пустой объект
	$o1 = $port_c->query('get_blankobjt1');
	if (!($o1 instanceof sharpobj_data_item_data))
	{
		// Нам вернули объект не того типа
		$ok = false;
		echo "\nМетод get_blankobjt1 вернул объект не являющийся sharpobj_data_item_data \n";
		print_r($o1);
	}
	// Правим объект
	$o1->set('plain',array('a'=>18,'b'=>'trtrt'));
	// Добавляем объект в базу
	$id = $port_c->query('addt1',$o1);
	// Считываем объект из базы
	$o11 = $port_c->query('gett1',$id);
	if (!($o11 instanceof sharpobj_data_item_data))
	{
		// Нам вернули объект не того типа
		$ok = false;
		echo "\nМетод gett1 вернул объект не являющийся sharpobj_data_item_data \n";
		print_r($o11);
	}
	if ($o11->get('plain','a')!==18 AND $o11->get('plain','b')!=='trtrt')
	{
		// Нам вернули объект не того типа
		$ok = false;
		echo "\nМетод gett1 вернул объект с неправильными данными \n";
		print_r($o11);
	}
	// 
	
	/*
    $dataobj = new sharpobj_data_item_int();
    $dataobj->set('plain',10);
    
    $res = $port_c->query('pr','test',$dataobj,'ps');

    if ($res->get('plain') != ($dataobj->get('plain')+2))
    {
        echo "\nСбой в цепочке: результат не соответствует ожидаемому\n";
        print_r($res);
        $ok = false;
    }
    */
	// Считаем, сколько заняло исполнение
	echo round(microtime(true) - $start,4);
    echo '</pre>';
    return $ok;
}

function atest_mod_sharpobj_func_standartcalls()
{   // Тестируем работу стандартных вызовов

    $ok = true;
	$start = microtime(true);
    echo '<pre>';
    // Процессор
    class atest_mod_sharpobj_func_p2 extends sharpobj_processor
    {
		function __construct()
		{
			// Создаем справочники
			// Задаем формат справочника
			$format = new sharpobj_storage_format();
			$format->addItem('a','a_int','int');
			$format->addItem('b','b_str','string');
			// Объявляем справочник
			$DB_t1 = new sharpobj_storage_simplemysql($format,
			array('tbname'=>'atest_sharpobj_t1','idfield'=>'id'));
			// Подключаемся к базе
			// $mysql_conn = mysql_connect('localhost','root','');
			// mysql_select_db('my-site-srv',$mysql_conn);
			// $DB_t1->setConnection($mysql_conn);
			// Добавляем справочник к процессору
			$this->storageAdd('t1',$DB_t1);
		}
    }
	// Создаем экземпляр процессор
    $proc1 = new atest_mod_sharpobj_func_p2();
    // Серверный порт
    $port_s1 = new sharpobj_port_server('proc1',$proc1);
    // Клиентский порт
    $port_c = new sharpobj_port_client_int('port_s1',$port_s1);
    
	// *********************
	// Работаем с клиентом
	// Получаем пустой объект
	$o1 = $port_c->query('sc_getObj_t1',null);
	if (!($o1 instanceof sharpobj_data_item_data))
	{
		// Нам вернули объект не того типа
		$ok = false;
		echo "\nМетод ac_getObj_t1 вернул объект не являющийся sharpobj_data_item_data \n";
		print_r($o1);
	}
	$o1->set('sql',167,'a');
	$o1->set('sql','TestTest!\'','b');
	if (!$id = $port_c->query('sc_insert_t1',$o1))
	{
		$ok = false;
		echo "\nВставка в базу не удалась \n";
	}
	$o11 = $port_c->query('sc_get_t1',$id);
	if (!($o11 instanceof sharpobj_data_item_data))
	{
		// Нам вернули объект не того типа
		$ok = false;
		echo "\nМетод sc_get_t1 вернул объект не являющийся sharpobj_data_item_data \n";
		print_r($o11);
	}
	if ($o11->get('plain','a')!==$o1->get('plain','a') 
				AND $o11->get('plain','b')!==$o11->get('plain','b'))
	{
		// Нам вернули объект не того типа
		$ok = false;
		echo "\nМетод sc_get_t1 вернул объект с неправильными данными \n";
		print_r($o11);
	}
	
	// Проверяем возможность вызова sql-функции
	$port_c->query('sc_sqlAction_t1',"UPDATE #!table# SET `a_int`='10' WHERE id={$id};");	
    $o12 = $port_c->query('sc_get_t1',$id,'proc1');
    if ($o12->getP('a')!==10)
    {
		$ok = false;
		echo "\nsql-запрос на обновление не выполнен или выполнен неправильно\n";
		print_r($o12);  
    }

	$port_c->query('sc_delete_t1',$id);
	$o12 = $port_c->query('sc_get_t1',$id);
	if ($o12 !== false)
	{
		// Нам вернули объект не того типа
		$ok = false;
		echo "\nМетод sc_delete_t1 не смог удалить объект \n";
	}
	$oo1 = $port_c->query('sc_getListAll_t1',new sharpobj_data_item_listlimit(10,3));
	foreach ($oo1 as $o13)
	{
		if (!is_int($o13->getId()))
		{
			$ok = false;
			echo $o13->getId();echo var_dump($o13->getId());
			echo "\nМетод sc_getListAll_t1 вернул неправильный список массива \n";
		}
	}

	// Считаем, сколько заняло исполнение
	echo round(microtime(true) - $start,6);
    echo '</pre>';
    return $ok;
}


function atest_mod_sharpobj_func_mysqlflex()
{   // Тестируем работу стандартных вызовов

    $ok = true;
	$start = microtime(true);
    echo '<pre>';
    // Процессор
    class atest_mod_sharpobj_func_p3 extends sharpobj_processor
    {
		function __construct()
		{
			// Создаем справочники
			// Объявляем справочник
			$DB_t1 = new sharpobj_storage_mysql_flex(null,
			array('tbname'=>'atest_sharpobj_flex_data'));
			// Подключаемся к базе
			// $mysql_conn = mysql_connect('localhost','root','');
			// mysql_select_db('my-site-srv',$mysql_conn);
			// $DB_t1->setConnection($mysql_conn);
			// Добавляем справочник к процессору
			$this->storageAdd('t1',$DB_t1);
		}
		function act_countup($id)
		{
			//
			return $this->storageLink('t1')->countUp($id,'ttt');
		}
		function act_ct($dataobj=null)
		{
		    // Создание таблицы в БД
			return $this->storageLink('t1')->createTable();
		}
    }
	// Создаем экземпляр процессор
    $proc1 = new atest_mod_sharpobj_func_p3();
    // Серверный порт
    $port_s1 = new sharpobj_port_server('proc1',$proc1);
    // Клиентский порт
    $port_c = new sharpobj_port_client_int('port_s1',$port_s1);
    // Получаем пустой объект
	// $o1 = $port_c->query('proc1','sc_getObj_t1');
	
	// $port_c->query('ct',null,'proc1');
	// Создаем контейнер с данными
	$o1 = new sharpobj_data_item_data();
	// Создаем формат
	$o1->addItem('qqq','int',array('len_max'=>255));
	$o1->addItem('bbb','int',array('len_max'=>255));
	$o1->addItem('aaa','string',array('len_max'=>255));
	$o1->addItem('dt','data');
	$o1->addItem('dt/qwe','int');
	$o1->addItem('dt/rty','string');
	// echo '111';
	$o1->setId($id = time());
	$o1->set('plain',null,'qqq');
	$o1->set('plain',321,'bbb');
	$o1->set('plain','test','aaa');
	$o1->set('plain',588,'dt/qwe');
	$o1->set('plain','test2','dt/rty');
	// print_r($o1->get('rdata'));
	// print_r($o1);


	// Добавляем данные
	$o2 = $port_c->query('sc_insert_t1',$o1);
	// Извлекаем данные
	$o3 = $port_c->query('sc_get_t1',$id);
	$o3->set('plain',444,'bbb');
	$o3->set('plain','test3','dt/rty');
	$o3->addItem('ttt','int',array('len_max'=>255));
	$o3->set('plain',555,'ttt');
	// Обновляем данные
	$o3 = $port_c->query('sc_update_t1',$o3);

	// Увеличиваем значение на единицу
	$o3 = $port_c->query('countup',$id);
	// Извлекаем данные
	$o4 = $port_c->query('sc_get_t1',$id);
	// print_r($o4->get('rdata'));
	// Проверяем данные
	if (		$o4->get('plain','aaa')!=='test'
			OR $o4->get('plain','bbb')!==444
			OR $o4->get('plain','qqq')!==null
			OR $o4->get('plain','ttt')!==556
			OR $o4->get('plain','dt/qwe')!==588
			OR $o4->get('plain','dt/rty')!=='test3'
		)
	{
		$ok = false;
		echo "\nОшибка: из базы вернулись неправильные значения\n";
		echo "Возвращенный объект:\n";
		print_r($o4);
		echo "Исходный объект:\n";	
		print_r($o1);
		foreach ($o4 as $iname=>$item)
		{
			echo "{$iname}={$item->get('html')}\n";
		}	
	}

	// Запрашиваем ограниченный список
	$list1 = $port_c->query('sc_getListAll_t1',new sharpobj_data_item_listlimit(10,5),'proc1');
	foreach ($list1 as $o5)
	{
		// Перебираем результат
		$str = "{$o5->getId()}-{$o5->get('html','aaa')}\n";
		// echo $str;
	}
;
	if (($count = count($list1))!==10)
	{
		$ok = false;
		echo "\nОшибка: список должен состояит из 10 значений, а не из {$count} (возможно, таблица еще не наполнилась данными, обновите страницу)\n";
	}
	if ($port_c->query('sc_count_t1') > 20)
	{
		// Удаляем данные
		$port_c->query('sc_delete_t1',$id);
	}
	unset($o1);
	unset($o2);
	unset($o3);
	unset($o4);
	unset($o5);
	unset($list1);
	unset($proc1);
	unset($port_s1);
	unset($port_c);
	
	// !!! Еще раз все то же самое, но с заданным форматом данных в хранилище
	// Процессор
    class atest_mod_sharpobj_func_p4 extends sharpobj_processor
    {
		function __construct()
		{
			// Создаем справочники
			// Создаем контейнер с данными
			$o1 = new sharpobj_data_item_data();
			// Создаем формат
			$o1->addItem('qqq','int',array('len_max'=>255));
			$o1->addItem('bbb','int',array('len_max'=>255));
			$o1->addItem('aaa','string',array('len_max'=>255));
			$o1->addItem('dt','data');
			$o1->addItem('dt/qwe','int');
			$o1->addItem('dt/rty','string');
			// Объявляем справочник
			$DB_t1 = new sharpobj_storage_mysql_flex($o1,
			array('tbname'=>'atest_sharpobj_flex_data'));
			// Подключаемся к базе
			// $mysql_conn = mysql_connect('localhost','root','');
			// mysql_select_db('my-site-srv',$mysql_conn);
			// $DB_t1->setConnection($mysql_conn);
			// Добавляем справочник к процессору
			$this->storageAdd('t1',$DB_t1);
		}
		function act_countup($id)
		{
			//
			return $this->storageLink('t1')->countUp($id,'ttt');
		}
		function act_ct($dataobj=null)
		{
			return $this->storageLink('t1')->createTable();
		}
    }
	// Создаем экземпляр процессор
    $proc1 = new atest_mod_sharpobj_func_p4();
    // Серверный порт
    $port_s1 = new sharpobj_port_server('proc1',$proc1);
    // Клиентский порт
    $port_c = new sharpobj_port_client_int('port_s1',$port_s1);
    // Получаем пустой объект
	$o1 = $port_c->query('sc_getObj_t1',null);
	$o1->setId($id = (1000+time()));
	$o1->set('plain',null,'qqq');
	$o1->set('plain',321,'bbb');
	$o1->set('plain','test','aaa');
	$o1->set('plain',588,'dt/qwe');
	$o1->set('plain','test2','dt/rty');
	// print_r($o1->get('rdata'));
	// print_r($o1);


	// Добавляем данные
	$o2 = $port_c->query('sc_insert_t1',$o1,'proc1');
	// Извлекаем данные
	$o3 = $port_c->query('sc_get_t1',$o2,'proc1');
	$o3->set('plain',444,'bbb');
	$o3->set('plain','test3','dt/rty');
	$o3->addItem('ttt','int',array('len_max'=>255));
	$o3->set('plain',555,'ttt');
	// Обновляем данные
	$o3 = $port_c->query('sc_update_t1',$o3);
			// Увеличиваем значение на единицу
	$o3 = $port_c->query('countup',$id);
	// Извлекаем данные
	$o4 = $port_c->query('sc_get_t1',$id);
	// print_r($o4->get('rdata'));
	// Проверяем данные
	if (	$o4->get('plain','aaa')!=='test'
			OR $o4->get('plain','bbb')!==444
			OR $o4->get('plain','qqq')!==null
			OR $o4->get('plain','dt/qwe')!==588
			OR $o4->get('plain','dt/rty')!=='test3'
		)
	{
		$ok = false;
		echo "\nОшибка: из базы вернулись неправильные значения\n";
		print_r($o4);	
		foreach ($o4 as $iname=>$item)
		{
			echo "{$iname}={$item->get('html')}\n";
		}	
	}	
	if ($port_c->query('sc_count_t1',null) > 20)
	{
		// Удаляем данные
		$port_c->query('sc_delete_t1',$id);
	}
	
	// Считаем, сколько заняло исполнение
	echo round(microtime(true) - $start,6);
    echo '</pre>';
    return $ok;
}


function atest_mod_sharpobj_func_overload()
{   // Перегрузку методов

    $ok = true;
	$start = microtime(true);
    echo '<pre>';
    // Процессор
    class atest_mod_sharpobj_func_oferload_p extends sharpobj_processor
    {
		function __construct()
		{
			// Создаем справочники
			// Задаем формат справочника
			$format = new sharpobj_storage_format();
			$format->addItem('a','a_int','int');
			$format->addItem('b','b_str','string');
			// Объявляем справочник
			$DB_t1 = new sharpobj_storage_simplemysql($format,
			array('tbname'=>'atest_sharpobj_t1','idfield'=>'id'));
			// Добавляем справочник к процессору
			$this->storageAdd('t1',$DB_t1);
		}
		function act_myTest($id)
		{
			//
			return $id;
		}
		function act_myTest2Args($v1,$v2)
		{
			//
			return $v1->getP()+$v2->getP();
		}
    }
    
    // Объявляем процессор
    $p = new atest_mod_sharpobj_func_oferload_p();
    
    // Тестируем обращение к функции act_
    if (15 !== ($a = $p->myTest(15)))
    {
    	// Ошибка
    	$ok = false;
    	echo "\nОшибка: перезагруженная функция act_ не вернула нужный аргумент\n";
    	var_dump($a);
    }
    
    // Тестируем обращение к функции sc_
    $obj = $p->sc_getObj_t1();
    if (sharpobj_iserror($obj)
    		OR !$obj
    		OR (!$obj instanceof sharpobj_data_item_data ))
    {
    	$ok = false;
    	echo "\nОшибка: перезагруженная функция sc_ не вернула нужный аргумент\n";
    	var_dump($obj);		
    }
    
    if (7 !== ($a =$p->myTest2Args(3,4)))
    {
    	// Ошибка
    	$ok = false;
    	echo "\nОшибка: перезагруженная функция act_ не вернула сумму двух аргументов\n";
    	var_dump($a);
    }

    if (8 !== ($a =$p->query('myTest2Args',6,2)) )
    {
    	// Ошибка
    	$ok = false;
    	echo "\nОшибка: query не вернула сумму двух аргументов\n";
    	var_dump($a);
    }
    
	// Считаем, сколько заняло исполнение
	echo round(microtime(true) - $start,6);
    echo '</pre>';
    return $ok;
}
?>